#include "toolmanager.h"

#include "tool/selecttool.h"
#include "tool/cloneitemtool.h"
#include "tool/moveitemtool.h"
#include "tool/placecircletool.h"
#include "tool/placecirculararctool.h"
#include "tool/placeellipsetool.h"
#include "tool/placerectangletool.h"

#include "command/command.h"

#include "view/scene.h"

#include <QActionGroup>
#include <QGraphicsSceneMouseEvent>

namespace SymbolEditor
{

    ToolManager::ToolManager(QObject *parent):
        QObject(parent)
    {
        m_defaultTool = new SelectTool(this);
        m_tools << m_defaultTool
                << new CloneItemTool(this)
                << new MoveItemTool(this)
                << new PlaceCircleTool(this)
                << new PlaceCircularArcTool(this)
                << new PlaceEllipseTool(this)
                << new PlaceRectangleTool(this);

        m_actionGroup = new QActionGroup(this);
        for (auto tool : m_tools)
        {
            auto action = tool->action();
            action->setActionGroup(m_actionGroup);
            m_actionToTool.insert(action, tool);
        }

        connect(m_actionGroup, &QActionGroup::triggered,
                this, [this](QAction *action)
        {
            setActiveTool(m_actionToTool.value(action));
        });

        for (auto tool : m_tools)
        {
            connect(tool, &AbstractTool::newCommandAvailable,
                    this, &ToolManager::appendNewCommand);
        }

        m_defaultTool->action()->setChecked(true);
        setActiveTool(m_defaultTool);
    }

    ToolManager::~ToolManager()
    {
    }

    QList<QAction *> ToolManager::actions() const
    {
        return m_actionGroup->actions();
    }

    void ToolManager::setScene(Scene *scene)
    {
        if (m_scene != nullptr)
        {
            m_scene->removeEventFilter(this);
        }

        m_scene = scene;

        if (m_scene != nullptr)
        {
            m_scene->installEventFilter(this);
        }

        setActiveTool(m_activeTool);
    }

    void ToolManager::applySettings(const LeGraphicsView::Settings &settings)
    {
        Q_UNUSED(settings);
    }

    void ToolManager::setActiveTool(AbstractTool *tool)
    {
        if (m_activeTool != nullptr)
        {
            m_activeTool->desactivate();
        }

        m_activeTool = tool;

        if (m_activeTool != nullptr)
        {
            m_activeTool->activate(m_scene);
            emit taskWidgetsChanged(m_activeTool->widgets());
        }
        else
        {
            emit taskWidgetsChanged(QList<QWidget *>());
        }
    }

    UndoCommand *ToolManager::nextPendingCommand()
    {
        if (m_pendingCommands.isEmpty())
        {
            return nullptr;
        }
        return m_pendingCommands.takeFirst();
    }

    bool ToolManager::hasPendingCommand() const
    {
        return !m_pendingCommands.isEmpty();
    }

    void ToolManager::appendNewCommand()
    {
        m_pendingCommands.append(m_activeTool->nextPendingCommand());
        emit newCommandAvailable();
    }

    bool ToolManager::eventFilter(QObject *watched, QEvent *event)
    {
        Q_ASSERT(watched == m_scene);

        switch(event->type())
        {
            case QEvent::GraphicsSceneMousePress:
            {
                auto gsmEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
                if (gsmEvent->flags().testFlag(Qt::MouseEventCreatedDoubleClick))
                {
                    return true;
                }
                return m_activeTool->mouseClickEvent(gsmEvent);
            }
            case QEvent::GraphicsSceneMouseDoubleClick:
            {
                auto gsmEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
                return m_activeTool->mouseDoubleClickEvent(gsmEvent);
            }
            case QEvent::GraphicsSceneMouseMove:
            {
                auto gsmEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
                return m_activeTool->mouseMoveEvent(gsmEvent);
            }
            default:
                return false;
        }
    }}


